package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.help.SearchCustomerHelp;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.lfasr.util.StringUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.model.SearchCustomerCompanyModel;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.SearchCustomerDataService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.SearchCustomerCompanyEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SoukeMealEnum;
import com.xbongbong.pro.enums.errorcodes.ContactErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SearchCustomerErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.searchcustomer.pojo.TransferStatusPojo;
import com.xbongbong.pro.searchcustomer.pojo.dto.Clue;
import com.xbongbong.pro.searchcustomer.pojo.dto.SearchCustomerCallbackDTO;
import com.xbongbong.pro.searchcustomer.pojo.dto.SearchCustomerDataDTO;
import com.xbongbong.pro.searchcustomer.pojo.vo.SearchCustomerMsgVO;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author shian
 * @create 2019-08-14 11:26
 * @Description
 */
@Service("searchCustomerDataService")
public class SearchCustomerDataServiceImpl implements SearchCustomerDataService {

    private static final Logger LOG = LoggerFactory.getLogger(SearchCustomerDataServiceImpl.class);

    @Resource
    private SearchCustomerHelp searchCustomerHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private SearchCustomerCompanyModel searchCustomerCompanyModel;
    @Resource
    private PaasFormDataService paasFormDataService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SearchCustomerMsgVO addBatch(@Valid SearchCustomerDataDTO searchCustomerDataDTO) throws XbbException {
        SearchCustomerMsgVO searchCustomerMsgVO = new SearchCustomerMsgVO();
        long formId = searchCustomerDataDTO.getFormId();
        String corpid = searchCustomerDataDTO.getCorpid();
        String userId = searchCustomerDataDTO.getUserId();

        // 获取转客户或公海客户的数据
        String uid = searchCustomerDataDTO.getUid();
        LOG.info("uid =" + uid);
        // 判断登录的用户是否是主账号
        SearchCustomerCompanyEntity soukeEntity = searchCustomerCompanyModel.getByCorpid(corpid, SoukeMealEnum.SOUKE.getType());
        if (soukeEntity != null && Objects.equals(userId, soukeEntity.getUserId())){
            uid = soukeEntity.getUid();
        }
        // 开通试用搜客，所有员工都可登录
        if (soukeEntity != null && soukeEntity.getExtraExpiry() - soukeEntity.getAddTime() < 4 * RedisConstant.LONG_DURATION
                && soukeEntity.getExtraExpiry() > DateUtil.getInt()) {
            uid = soukeEntity.getUid();
        }
        // 获取缓存中的数据
        String value = paasRedisHelper.getValue(RedisPrefixConstant.CLUE_TO_CUSTOMER, uid);
        LOG.info("搜客转客户数据 = " + value);
        if (StringUtil.isEmpty(value)) {
            searchCustomerMsgVO.setClueData(false);
            return searchCustomerMsgVO;
        }

        Map map = JSONObject.parseObject(value, Map.class);
        String transferData = (String) map.get("data");

        // 读取转客户或公海客户任务状态缓存
        String key = corpid + "_" + userId;
        TransferStatusPojo statusPojo = JsonHelperUtil.parseObject(paasRedisHelper.getValue(RedisPrefixConstant.CLUE_TO_CUSTOMER_STATUS, key), TransferStatusPojo.class);
        if (statusPojo != null && !statusPojo.getFinish()) {
            // 上次任务未结束
            throw new XbbException(SearchCustomerErrorCodeEnum.API_ERROR_401006);
        }

        // 清除转客户或公海客户任务状态缓存
        paasRedisHelper.removeValue(RedisPrefixConstant.CLUE_TO_CUSTOMER_STATUS, key);
        SearchCustomerCallbackDTO searchCustomerCallbackDTO = JSONObject.parseObject(transferData, SearchCustomerCallbackDTO.class);

        List<Clue> data = searchCustomerCallbackDTO.getClues();
        saveCustomer(searchCustomerDataDTO, data);

        searchCustomerMsgVO.setClueData(true);
        searchCustomerMsgVO.setCode(ErrorCodeEnum.API_SUCCESS.getCode());
        searchCustomerMsgVO.setMsg(ErrorCodeEnum.API_SUCCESS.getMsg());
        return searchCustomerMsgVO;
    }
    /**
     * 转客户的数据保存
     * @param searchCustomerDataDTO
     * @param data
     * @author 石安
     * @date 2019-09-02
     */
    @Async(value = "transferThreadPool")
    public void saveCustomer(SearchCustomerDataDTO searchCustomerDataDTO, List<Clue> data){
        String[] split = searchCustomerDataDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        List<String> successList = new ArrayList<>();
        List<String> errorList = new ArrayList<>();
        List<String> repeatList = new ArrayList<>();
        Set<String> errorMsgs = new HashSet<>();
        TransferStatusPojo transferStatusPojo = new TransferStatusPojo();
        transferStatusPojo.setTotalNum(data.size());
        String key = searchCustomerDataDTO.getCorpid() + "_" + searchCustomerDataDTO.getUserId();

        // 是否往form_data表中插入数据
        int noApprovalRequired = 1;
        int nowRowNum = 0;
        for (Clue clue : data) {
            try {
                nowRowNum ++;
                // 每隔5条/数据导完时，刷新一次当前导入状态
                if (nowRowNum == 1 || nowRowNum%5 == 0 || nowRowNum >= data.size()) {
                    paasRedisHelper.setValue(RedisPrefixConstant.CLUE_TO_CUSTOMER_STATUS, key, transferStatusPojo, RedisConstant.TINY_DURATION);
                }
                // 将搜客的客户按模糊匹配模板转客户数据
                JSONObject jsonObject = searchCustomerHelp.changeData(clue, searchCustomerDataDTO);

                FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
                BeanUtil.copyProperties(searchCustomerDataDTO, formDataAddDTO);
                formDataAddDTO.setDataList(jsonObject);
                formDataAddDTO.setSerialNo("");
                FormDataAddVO formDataAddVO = paasFormDataService.add(formDataAddDTO);
                if (PaasConstant.FORM_ADD_PROCESS_RETURN_CODE.equals(formDataAddVO.getCode())) {
                    noApprovalRequired = 0;
                }
                int successNum = transferStatusPojo.getSuccessNum();
                transferStatusPojo.setSuccessNum(++successNum);
                successList.add(clue.getPid());
                transferStatusPojo.setSuccessPids(successList);
            } catch (XbbException e) {
                LOG.error(clue.getEntname() + "转失败原因(change customer error)：", e);
                if (Objects.equals(SystemErrorCodeEnum.API_ERROR_100034.getCode(), e.getCode()) || Objects.equals(ContactErrorCodeEnum.API_ERROR_204008.getCode(), e.getCode())) {
                    Integer repeatNum = transferStatusPojo.getRepeatNum();
                    transferStatusPojo.setRepeatNum(++repeatNum);
                    repeatList.add(clue.getPid());
                    transferStatusPojo.setRepeatPids(repeatList);
                }
                int errorNum = transferStatusPojo.getErrorNum();
                transferStatusPojo.setErrorNum(++errorNum);
                errorMsgs.add(e.getMsg());
                transferStatusPojo.setErrorMsgs(errorMsgs);
                errorList.add(clue.getPid());
                transferStatusPojo.setErrorPids(errorList);
            }
        }

        // 将转换结果存Redis缓存中
        transferStatusPojo.setFinish(true);
        transferStatusPojo.setNoApprovalRequired(noApprovalRequired);
        paasRedisHelper.setValue(RedisPrefixConstant.CLUE_TO_CUSTOMER_STATUS, key, transferStatusPojo, RedisConstant.TINY_DURATION);

    }
    @Override
    public SearchCustomerMsgVO getStatus(@Valid SearchCustomerDataDTO searchCustomerDataDTO) {
        SearchCustomerMsgVO searchCustomerMsgVO = new SearchCustomerMsgVO();
        String key = searchCustomerDataDTO.getCorpid() + "_" + searchCustomerDataDTO.getUserId();
        String target = searchCustomerDataDTO.getTarget();
        TransferStatusPojo transferStatusPojo = JsonHelperUtil.parseObject(paasRedisHelper.getValue(RedisPrefixConstant.CLUE_TO_CUSTOMER_STATUS, key), TransferStatusPojo.class);

        if (transferStatusPojo == null) {
            return searchCustomerMsgVO;
        }
        int noApprovalRequired = transferStatusPojo.getNoApprovalRequired();
        String info = noApprovalRequired == 1 ? I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG) : I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG);

        // 记录转成功与失败的条数
        int totalNum = transferStatusPojo.getTotalNum();
        int successNum = transferStatusPojo.getSuccessNum();
        int errorNum = transferStatusPojo.getErrorNum();
        int repeatNum = transferStatusPojo.getRepeatNum();
        int complete = successNum + errorNum;

        if(complete < totalNum){
            searchCustomerMsgVO.setCode(3);
            searchCustomerMsgVO.setMsg(String.format(I18nMessageUtil.getMessage(I18nStringConstant.CLUE_IN_PROCESS), target));
            searchCustomerMsgVO.setFinish(transferStatusPojo.getFinish());
            searchCustomerMsgVO.setTotalNum(totalNum);
            searchCustomerMsgVO.setCompleteNum(complete);
            return searchCustomerMsgVO;
        }

        Set<String> errorMsgs = transferStatusPojo.getErrorMsgs();
        String errorMsg = "";
        if (CollectionUtils.isNotEmpty(errorMsgs)) {
            errorMsg = errorMsgs.stream().collect(Collectors.joining(","));
        }
        // 转数据的结果给前端展示
        if (successNum == totalNum) {
            searchCustomerMsgVO.setCode(0);
            searchCustomerMsgVO.setMsg(String.format(I18nMessageUtil.getMessage(I18nStringConstant.CLUE_PROCESS_SUCCESS), target) + info);
        } else if (errorNum > 0 && successNum > 0) {
            if ( repeatNum > 0) {
                searchCustomerMsgVO.setCode(1);
                searchCustomerMsgVO.setMsg(String.format(I18nMessageUtil.getMessage(I18nStringConstant.CLUE_TRANSFER_INFO_A), target, successNum, repeatNum, errorMsg, errorNum) + info);
            } else {
                searchCustomerMsgVO.setCode(2);
                searchCustomerMsgVO.setMsg(String.format(I18nMessageUtil.getMessage(I18nStringConstant.CLUE_TRANSFER_INFO_B), target, successNum, repeatNum, errorMsg) + info);
            }
        } else if (errorNum == totalNum) {
            searchCustomerMsgVO.setCode(2);
            searchCustomerMsgVO.setMsg(String.format(I18nMessageUtil.getMessage(I18nStringConstant.CLUE_TRANSFER_INFO_C), target, errorMsg));
            if(errorNum == repeatNum){
                searchCustomerMsgVO.setCode(2);
                searchCustomerMsgVO.setMsg(String.format(I18nMessageUtil.getMessage(I18nStringConstant.CLUE_TRANSFER_INFO_D), target, errorMsg, repeatNum));
            }
        }
        searchCustomerMsgVO.setFinish(transferStatusPojo.getFinish());
        searchCustomerMsgVO.setTotalNum(totalNum);
        searchCustomerMsgVO.setCompleteNum(complete);
        return searchCustomerMsgVO;
    }
}
